function reactive(data) {
  //数据劫持
  let proxy = new Proxy(data, handler);
  return proxy;
}
//属性劫持的相关操作
const handler = {
  get(target, key) {
    //传入依赖
    track(target, key);
    let value = Reflect.get(target, key);
    //对象递归劫持
    return typeof value === 'object' ? reactive(value) : value;
  },
  set(target, key, value) {
    console.log(target,key,value)
    Reflect.set(target, key, value);
    //调用依赖
    trigger(target, key);
  }
}

// effect注册栈
const effectLists = [];
/**
* targetWeakMap{
*      target: Map{
*          key: Set()
*      }
* }
*/
const targetWeakMap = new WeakMap();

// 依赖收集
function track(target, key) {
  //数组的length-1才能访问到最后一个依赖
  //最后一个依赖一定是当前需要的依赖
  const effect = effectLists[effectLists.length - 1];
  let targetMap = targetWeakMap.get(target);
  if (targetMap === undefined) {
    //创建map
    targetMap = new Map();
    //设置键为target值为new Map(这个是外层的)
    targetWeakMap.set(target, targetMap);
  }
  let keySet = targetMap.get(key);
  if (keySet === undefined) {
    //创建set
    keySet = new Set();
    //设置键为传入的key值为new Set
    targetMap.set(key, keySet);
  }
  //添加new set添加值
  if (effect) {
    if (!keySet.has(effect)) {
      //添加到依赖
      keySet.add(effect)
    }
  }
}

// 依赖更新
function trigger(target, key) {
  debugger;
  let targetMap = targetWeakMap.get(target);
  if (targetMap === undefined) {
    return;
  }

  let keySet = targetMap.get(key);
  if (keySet === undefined) {
    return;
  }
  keySet.forEach(effect => effect());
}

// 计算属性
function computed(fn) {
  const ef = effect(fn, { computed: true, lazy: true });
  return {
    effect: ef,
    get value() {
      return ef();
    }
  }
}

/**
 * 我们在这里的时候会收集副作用,等到它的依赖变化的时候
 * 这个函数就会执行
 */
// 收集副作用
function effect(fn, options = {}) {
  //创建副作用
  const rFn = createReactEffect(fn, options);
  if (!options.lazy) { //computed不是立即执行
    rFn();
  }
  return rFn;
}

// 创建响应式副作用
function createReactEffect(fn, options = {}) {
  //这里返回一个包裹副作用的函数
  function reactiveEffect(...args) {
    return run(reactiveEffect, fn, args);
  }
  return reactiveEffect;
}

// 执行副作用
function run(reactiveEffect, fn, args) {
  //这里判断队列中是否有这个函数
  if (!effectLists.includes(reactiveEffect)) {
    try {
      //加入队列
      effectLists.push(reactiveEffect);
      //函数最终调用在这
      return fn(...args);
    } finally {
      effectLists.pop();
    }
  }
}
